/**
 * @file sm2.h
 * @brief 实现国密sm2的算法
 * @license BSD
 */

#ifndef SM_SM2_H
#define SM_SM2_H

#include "ecfp.h"
#include "ecf2m.h"
#include "sm3.h"

#ifdef __cplusplus
extern "C" {
#endif


typedef struct SM2Work_st
{
	ECPoint G;
	UInteger n;
	size_t size;
	const ECWork* ec;
} SM2Work;

enum SM2_ERR_CODE {
	SM2_ERR_OK,
	
};

/** */
#define SM2_Size(sm2) ((sm2)->size)

/**
 *
 * @param [out] sm2
 * @param [in] size
 * @param [in] 
 * @param [in] a,b 
 * @param [in] G
 * @param [in] n 
 */
void SM2_Initialize(SM2Work *sm2, size_t size, const uint8_t *G, uint8_t* n, const ECWork *ec);

void SM2_ZA(SM2Work *sm2, const uint8_t *id, size_t idlen, const uint8_t *PA, uint8_t ZA[SM3_HASH_LENGTH]);

void SM2_PublicKey(SM2Work *sm2, const uint8_t *dA, uint8_t *PA);

/**
 * 对数据进行签名
 * @param [in] sm2
 * @param [in] privateKey
 * @param [in]
 * @param [in] m, mlen 签名数据以及长度
 * @param [in] k 随机数
 * @param [out] rs 签名数据，
 */
void SM2_Sign(const SM2Work* sm2, const uint8_t *dA, const uint8_t ZA[SM3_HASH_LENGTH], const uint8_t *m, size_t mlen, const uint8_t *k, uint8_t *rs);

/**
 * 对数据进行验签
 */
bool SM2_Verify(const SM2Work* sm2, const uint8_t *PA, const uint8_t ZA[SM3_HASH_LENGTH], const uint8_t *m, size_t mlen, const uint8_t *rs);

/** 密文数据长度比明文数据长度多出的部分长度。*/
size_t SM2_CipherStubLength(const SM2Work *sm2);


/**
 * 实现SM2基于素数域的加密算法，参考第4部分《公钥加密算法》6节
 * @param [in] publicKey 公钥，即6.1节描述的PB
 * @param [in] random 随机数，长度为SM2_Size
 * @param [in] plain, plainLength 明文数据即长度
 * @param [out] cipher 密文数据，密文的长度通过SM2_CipherLength计算
 * @return
 */
bool SM2_Encrypt(const SM2Work *sm2, const uint8_t *publicKey, const uint8_t *random, uint8_t *plain, size_t plainLength, uint8_t* cipher);

/**
 * 实现SM2基于素数域的解密算法，参考第4部分《公钥加密算法》7节
 * @param [in] sm2 基于素数域的SM2参数
 * @param [in] privateKey 私钥，长度为SM
 * @return true表示解密成功，false表示失败
 */
bool SM2_Decrypt(const SM2Work *sm2, const uint8_t *privateKey, const uint8_t *cipher, size_t cipherLength, uint8_t *plain);

#ifdef __cplusplus
} // extern "C" {
#endif


#endif // SM_SM2_H
